﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace GingerBeard.IDL
{
    public partial class IDLVariable
    {
        public override bool GeneratePre_CSharp(CompileSettings settings)
        {
            String varType = Type;
            String varName = Name;

			String targetType = varType;
			String targetName = varName;
			String targetInitialiser = "";

			if (varType.ToLower().Contains("array"))
			{
				int firstBracket = varType.IndexOf('[');
				int lastBracket = varType.IndexOf(']');
				String arrayType = varType.Substring(firstBracket + 1, lastBracket - firstBracket - 1);
				int arrayCount = 1;
				varType = varType.Substring(lastBracket + 1);

				if (varType.Contains("["))
				{
					firstBracket = varType.IndexOf('[');
					lastBracket = varType.IndexOf(']');
					String countString = varType.Substring(firstBracket + 1, lastBracket - firstBracket - 1);

					if (!int.TryParse(countString, out arrayCount))
					{
						throw new Exception("Invalid characters found in array count specifier");
					}

					targetType = arrayType + "[]";
					targetName = varName;
					if (arrayCount > 1)
						targetInitialiser = "= new " + arrayType + "[" + arrayCount + "]";
				}
				else
				{
					targetType = "List<" + arrayType + ">";
					targetName = varName;
					targetInitialiser = "= new " + targetType + "()";
				}
			}
			else if (varType.ToLower().Contains("link"))
			{
				int firstBracket = varType.IndexOf('[');
				int lastBracket = varType.IndexOf(']');
				String linkType = varType.Substring(firstBracket + 1, lastBracket - firstBracket - 1);

				targetName = varName;
				targetType = linkType;
				targetInitialiser = "";
			}

			settings.WriteOutputLine("private " + targetType + " _" + targetName + (targetInitialiser.Length > 0 ? " " : "") + targetInitialiser + ";");
			if (Obsolete != null)
			{
				settings.WriteOutputLine("[Obsolete(\"" + Obsolete + "\")]");
			}
			settings.WriteOutputLine("public " + targetType + " " + targetName);
			settings.WriteOutputLine("{");
			settings.WriteOutputLine("\tget { return _" + targetName + "; }");
			settings.WriteOutputLine("\tset { _" + targetName + " = value; }");
			settings.WriteOutputLine("}");

            return true;
        }

        public override void GeneratePost_CSharp(CompileSettings settings)
        {

        }
    }
    public partial class IDLObject
    {
        public override bool GeneratePre_CSharp(CompileSettings settings)
        {
            settings.WriteOutputLine("public class " + Name);
            settings.WriteOutputLine("{");
            return true;
        }

        public override void GeneratePost_CSharp(CompileSettings settings)
        {
            settings.WriteOutputLine("}");
        }
    }
    public partial class IDLEnum
    {
        public override bool GeneratePre_CSharp(CompileSettings settings)
        {
            settings.WriteOutputLine("public enum " + Name);
            settings.WriteOutputLine("{");
            String[] values = Values.Split(',');
            foreach (String value in values)
            {
                settings.WriteOutputLine("\t" + value + ",");
            }
            settings.WriteOutputLine("};");
            return true;
        }

        public override void GeneratePost_CSharp(CompileSettings settings)
        {

        }
    }
    public partial class IDLNamespace
    {
        public override bool GeneratePre_CSharp(CompileSettings settings)
        {
            settings.WriteOutputLine("namespace " + this.Name);
            settings.WriteOutputLine("{");
            return true;
        }

        public override void GeneratePost_CSharp(CompileSettings settings)
        {
            settings.WriteOutputLine("}");
        }
    }
    public partial class IDLIfLanguage
    {
        public override bool GeneratePre_CSharp(CompileSettings settings)
        {
			settings.Indent--;
            return Name.ToLower() == "csharp";
        }

        public override void GeneratePost_CSharp(CompileSettings settings)
        {
			settings.Indent++;
        }
    }
    public partial class IDLTypes
    {
        public override bool GeneratePre_CSharp(CompileSettings settings)
        {
			settings.Indent--;
            return true;
        }

        public override void GeneratePost_CSharp(CompileSettings settings)
        {
			settings.Indent++;
        }
    }
    public partial class IDLType
    {
        public override bool GeneratePre_CSharp(CompileSettings settings)
        {
			if (Name != ActualType)
				settings.WriteOutputLine("using " + Name + " = " + ActualType + ";");
            return true;
        }

        public override void GeneratePost_CSharp(CompileSettings settings)
        {

        }
    }
	public partial class IDLContainer
	{
		public override bool GeneratePre_CSharp(CompileSettings settings)
		{
			// Figure out what kinds of objects live under this node
			
			return false;
		}

		public override void GeneratePost_CSharp(CompileSettings settings)
		{

		}
	}
    public partial class IDL
    {
        public override bool GeneratePre_CSharp(CompileSettings settings)
        {
            settings.WriteOutputLine("// --------------------------------------------------------------------------------------------------");
            settings.WriteOutputLine("// BEGIN AUTOGENERATED CODE ");
            settings.WriteOutputLine("// --------------------------------------------------------------------------------------------------");
            settings.WriteOutputLine("// Assembly : " + Assembly.GetExecutingAssembly().ToString());
            settings.WriteOutputLine("// Time     : " + DateTime.Now);
            settings.WriteOutputLine("// Source   : " + SourceFilename);
            settings.WriteOutputLine("// --------------------------------------------------------------------------------------------------");
			settings.WriteOutputLine("using System;");
			settings.WriteOutputLine("using System.IO;");
			settings.WriteOutputLine("using System.Collections.Generic;");
			
            settings.WriteOutputLine("// --------------------------------------------------------------------------------------------------");
            settings.WriteOutputLine("namespace " + this.Name);
            settings.WriteOutputLine("{");
            return true;
        }

        public override void GeneratePost_CSharp(CompileSettings settings)
        {
			settings.Indent++;
			settings.WriteOutputLine("// Containers");

			// Generate containers
			List<IDLContainer> containers = FindNodesRecursive<IDLContainer>();
			foreach (IDLContainer container in containers)
			{
				settings.WriteOutputLine("public class " + container.Name);
				settings.WriteOutputLine("{");

				IDLObject containerObject = FindNamedNode(container.Type, true) as IDLObject;
				List<IDLObject> containerObjects = new List<IDLObject>();
				if (containerObject == null)
					throw new Exception(String.Format("Container '{0}' references object type '{1}' which doesn't exist", container.Name, container.Type));

				GatherSubObjects(containerObject, containerObjects);

				foreach (IDLObject subObj in containerObjects)
				{
					settings.WriteOutputLine("\t" + String.Format("List<{0}> _{0}List = new List<{0}>();", subObj.Name));
					settings.WriteOutputLine("\t" + String.Format("public List<{0}> {0}List", subObj.Name));
					settings.WriteOutputLine("\t" + "{");
					settings.WriteOutputLine("\t\t" + String.Format("get {{ return _{0}List; }}", subObj.Name));
					settings.WriteOutputLine("\t" + "}");
				}

				settings.Indent++;
				if (settings.CodeGenSaving != CodeGeneration.Off)
				{
					settings.WriteOutputLine("public static void Save(StreamWriter writer)");
					settings.WriteOutputLine("{");
					settings.WriteOutputLine("}");
				}

 				if (settings.CodeGenLoading != CodeGeneration.Off)
 				{
					settings.WriteOutputLine("public static void Load(StreamReader reader, )");
					settings.WriteOutputLine("{");
					settings.WriteOutputLine("}");
 				}
				settings.Indent--;

				settings.WriteOutputLine("}");
			}
			settings.Indent--;

            settings.WriteOutputLine("}");
            settings.WriteOutputLine("// --------------------------------------------------------------------------------------------------");
            settings.WriteOutputLine("// END AUTOGENERATED CODE");
            settings.WriteOutputLine("// --------------------------------------------------------------------------------------------------");
        }

		private static void GatherSubObjects(IDLNode node, List<IDLObject> subObjects)
		{
			IDLObject obj = node as IDLObject;
			if (obj != null)
			{
				if (!subObjects.Contains(obj))
					subObjects.Add(obj);
			}

			foreach (IDLNode n in node.Nodes)
			{
				IDLVariable var = n as IDLVariable;
				if (var != null)
				{
					// Is this a link or an array?
					if (var.Name.Contains("Link["))
					{
					}
					else if (var.Name.Contains("Array["))
					{
					}
				}
			}
		}
    }
	public partial class IDLContainerWriter
	{
		
	}
}
